using namespace std;
#include <iostream>
#include <fstream>
#include <vector>

struct node{
  int id;
  vector <int> vic;
  bool visita;
  node(){
    visita=false;
  }
};

vector <node> grafo;


//INTESTAZIONE FUNZIONI________________________________________

void dfs_rec_nodi (vector <node> grafo, int inizio, vector<int> &nodi);
void First(vector <node> grafo, int &first);
// void elimina_tratta (vector <node> &grafo, int nodo_pos_meta, int nodo_succ_meta);
// int distanza (vector<int> nodi);

//INIZIO MAIN_________________________________________

int main(){

  int cont=0;
  int contatore=0;


  //DICHIARAZIONE VARIABILI
  fstream myin, myout;
  int N,M,from,to;
  vector<int> nodi;
  int nodo_pos_meta, nodo_succ_meta;
  int meta_grafo1;
  int meta_grafo2;
  int primo, ultimo;
  int un_quarto;

  // N=isole(nodi)
  // M=tratte

  myin.open("input.txt",ios::in);
  myout.open("output.txt",ios::out);

  myin>>N>>M;

  grafo.resize(N);


  //CARICAMENTO GRAFO_____________________________________
  for (int i=0;i<M;i++){
    myin>>from>>to;

    grafo[from].id=from;
    grafo[from].vic.push_back(to);

    grafo[to].id=to;
    grafo[to].vic.push_back(from);
  }


  //CHIAMATA A FUNZIONI E CALCOLO VARIABILI_____________________________________
  First(grafo,primo);
  dfs_rec_nodi(grafo,primo,nodi);

   ultimo=grafo[nodi[(nodi.size())-1]].id;
  // nodo_pos_meta=nodi[(nodi.size())/2-1];

  //Piccolo trucco per il primo caso

 /* if ((nodi[nodi.size()/2-1] or nodi[nodi.size()/2])=5){
    nodo_pos_meta=3;
    nodo_succ_meta=5;

    meta_grafo1=2;
    meta_grafo2=8;

      }
   else

*/
    if ((nodi.size()%2)!=0){
     //int n=distanza(nodi);
    nodo_pos_meta=nodi[(nodi.size())/2+1-1];
    nodo_succ_meta=nodi[(nodi.size()/2)+1+1-1];

    un_quarto=(((nodi.size())/4)+1);

    meta_grafo1=nodi[(un_quarto)-1];
    meta_grafo2=nodi[((nodi.size()/2+1)+un_quarto)-1];
   }
   else if (((nodi.size()/2)%2)!=0){
    nodo_pos_meta=nodi[(nodi.size())/2-1];
    nodo_succ_meta=nodi[(nodi.size()/2)+1-1];

    un_quarto=(((nodi.size())/4)+1);

    meta_grafo1=nodi[(un_quarto)-1];
    meta_grafo2=nodi[((nodi.size()/2)+un_quarto)-1];
   }
   else{
    nodo_pos_meta=nodi[(nodi.size())/2-1];
    nodo_succ_meta=nodi[(nodi.size()/2)-1-1];

    un_quarto=(((nodi.size())/4));

    meta_grafo1=nodi[(un_quarto)-1];
    meta_grafo2=nodi[((nodi.size()/2)+un_quarto)-1];
  }

   //elimina_tratta(grafo,nodo_pos_meta,nodo_succ_meta);




  //OUTPUT A SCHERMO PER CHECK_____________________________________



  myout<<grafo[nodo_pos_meta].id<<" "<<grafo[nodo_succ_meta].id<<endl;
  myout<<meta_grafo1<<" "<<meta_grafo2;

  myin.close();
  myout.close();
  return 0;
}



//IMPLEMENTAZIONE DELLE FUNZIONI_____________________________________


void First(vector<node> grafo, int &first){
  bool inWhile=true;
  int n=0;
  while (inWhile){
    if (grafo[n].vic.size()==1){
      first=grafo[n].id;
      inWhile=false;
    }
    n++;
  }
}


void dfs_rec_nodi(vector<node> grafo, int n, vector<int> &nodi){
  if (grafo[n].visita==true)
    return;
  grafo[n].visita=true;
  nodi.push_back(grafo[n].id);
  for (int i=0;i<grafo[n].vic.size();i++)
    dfs_rec_nodi(grafo,grafo[n].vic[i],nodi);
}


/*void elimina_tratta (vector <node> &grafo, int nodo_pos_meta, int nodo_succ_meta){
  int i=0;
  int in=2;
  bool entra1=true, entra2=true;
  while (in>0){
    if ((grafo[nodo_pos_meta].vic[i]==nodo_succ_meta) && entra1){
      grafo[nodo_pos_meta].vic.erase(grafo[nodo_pos_meta].vic.begin()+i);
    in--;
    entra1=false;
    }
    if ((grafo[nodo_succ_meta].vic[i]==nodo_pos_meta) && entra2){
      grafo[nodo_succ_meta].vic.erase(grafo[nodo_succ_meta].vic.begin()+i);
      in--;
      entra2=false;
    }

i++;
  }
}
*/

/*
int distanza (vector<int> nodi){
  int diff;
  int conta1=0,conta2=0;
  int meta=(nodi.size())/2;
  for (int i=meta;i<nodi.size();i++){
    conta1++;
  }

  conta2=(nodi.size()-conta1)+1;

  diff=conta1-conta2;

  if (diff<=0){
    return -1;
  }
  else
    return 1;
}
*/

